using System;
using System.Collections.Generic;
using System.Linq;

namespace Windy.OpenLink.ObjectPools
{
    public class DynamicHierarchyObjectPool : HierarchyObjectPool, IObjectPool, IDynamicHierarchyObjectPool
    {
        public DynamicHierarchyObjectPool()
            : base(new Dictionary<string, IObjectPool>())
        { }

        #region IDynamicHierarchyObjectPool Members

        public virtual void AddSubPool(string path, IObjectPool subPool)
        {
            if (String.IsNullOrEmpty(path))
                throw new ArgumentException("path is null or empty.", "path");
            if (subPool == null)
                throw new ArgumentNullException("subPool", "subPool is null.");

            SubPools.Add(path, subPool);
        }

        public virtual bool RemoveSubPool(string path, RemoveSubPoolOptions options = RemoveSubPoolOptions.RemoveSubPoolObjects)
        {
            if (String.IsNullOrEmpty(path))
                throw new ArgumentException("path is null or empty.", "path");

            if (!SubPools.ContainsKey(path))
                return false;

            switch (options)
            {
                case RemoveSubPoolOptions.RemoveSubPoolObjects:
                    SubPools.Remove(path);
                    break;
                case RemoveSubPoolOptions.MoveToParent:
                    {
                        var subPool = GetSubPool<IObjectPool>(path);
                        SubPools.Remove(path);
                        foreach (var fo in subPool.AsEnumerable())
                        {
                            this[fo.Key] = fo.Value;
                        }
                    }
                    break;
                case RemoveSubPoolOptions.MoveToMostSuitablePool:
                    {
                        var subPool = GetSubPool<IObjectPool>(path);
                        SubPools.Remove(path);
                        foreach (var fo in subPool.AsEnumerable())
                        {
                            FindMostSuitableSubPool(fo.Key)[fo.Key] = fo.Value;
                        }
                    }
                    break;
                default:
                    throw new ArgumentOutOfRangeException("options", "options is not a RemoveSubPoolOptions value.");
            }

            return true;
        }

        public virtual TPool GetSubPool<TPool>(string path)
            where TPool : class, IObjectPool
        {
            return SubPools[path] as TPool;
        }

        public virtual bool HasSubPool(string path)
        {
            return SubPools.ContainsKey(path);
        }

        public virtual IEnumerable<string> SubPoolPaths { get { return SubPools.Keys; } }

        public virtual int SubPoolCount { get { return SubPools.Count; } }

        #endregion IDynamicHierarchyObjectPool Members
    }
}
